﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Domain.Model.Repositories;
using Domain.Model.Infractores;
using Domain.Model.Base;
using Infrastructure.Base.Persistence;
using Domain.Model.Direcciones;
using Domain.Model.LicenciasDeConduccion;
using Domain.Model.SecretariasDeTransito;


namespace Infrastructure.Base.InDatabase
{
    public class BInfractorRepository : InfractorRepository
    {
        private List<Infractor> lista;

        public BInfractorRepository()
        {
            this.lista = new List<Infractor>();

        }

        #region Métodos Heredados Generales
        
        public override void Insert(Infractor entity)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            TblInfractor obj = new TblInfractor();

            //Identidad
            obj.id = entity.Identity.Value.ToString();

            //Llaves Foráneas
            obj.pk_licenciaconduccion = entity.LicenciaConduccion.PK;

            //Campos Propios            
            obj.numIdentificacion = entity.NumIdentificacion;            
            obj.nombres = entity.Nombres;
            obj.apellidos = entity.Apellidos;
            obj.tipoIdentificacion = entity.TipoIdentificacion;

            //Objetos de Valor
            obj.domicilio = entity.Direccion.Domicilio;
            obj.municipio = entity.Direccion.Municipio;
            obj.localidad = entity.Direccion.Localidad;
            obj.codigoPostal = entity.Direccion.CodigoPostal;

            contexto.AddToTblInfractor(obj);
            contexto.SaveChanges();
            contexto.Dispose();
        }

        public override Infractor FromId(ObjectIdentity id)
        {
            String idString = id.Value.ToString();
            ContextoInfraccion contexto = new ContextoInfraccion();
            
            TblInfractor item = contexto.TblInfractor.Where(I => I.id == idString).FirstOrDefault();
            contexto.Dispose();
            
            if (item != null)
            {
                //El repositorio de infractor crea el objeto Licencia mediante un método privado
                Infractor oInfractor = new Infractor(new InfractorId(item.id), item.numIdentificacion, item.nombres, item.apellidos, item.tipoIdentificacion,
                    this.LicenciaConduccionFromPK((int)item.pk_licenciaconduccion),
                    new Direccion(item.domicilio, item.municipio, item.localidad, item.codigoPostal));


                //Asignar la llave primaria de la BD
                oInfractor.PK = item.pk_infractor;

                return oInfractor;
            }

            return null;
        }

        public override ObjectIdentity NextIdentity()
        {
            return new InfractorId(Guid.NewGuid().ToString().ToUpper());
        }

        public override void Update(Infractor entity)
        {
            String idString = entity.Identity.Value.ToString();
            ContextoInfraccion contexto = new ContextoInfraccion();

            TblInfractor obj = contexto.TblInfractor.Where(I => I.id == idString).FirstOrDefault();
            
            //Identidad
            obj.id = entity.Identity.Value.ToString();

            //Llaves Foráneas
            obj.pk_licenciaconduccion = entity.LicenciaConduccion.PK;

            //Campos Propios            
            obj.numIdentificacion = entity.NumIdentificacion;
            obj.nombres = entity.Nombres;
            obj.apellidos = entity.Apellidos;
            obj.tipoIdentificacion = entity.TipoIdentificacion;

            //Objetos de Valor
            obj.domicilio = entity.Direccion.Domicilio;
            obj.municipio = entity.Direccion.Municipio;
            obj.localidad = entity.Direccion.Localidad;
            obj.codigoPostal = entity.Direccion.CodigoPostal;

            contexto.SaveChanges();
            contexto.Dispose();
        }

        public override void Remove(ObjectIdentity id)
        {
            String idString = id.Value.ToString();            
            ContextoInfraccion contexto = new ContextoInfraccion();            
            
            TblInfractor obj = contexto.TblInfractor.Where(I => I.id == idString).FirstOrDefault();

            contexto.DeleteObject(obj);
            contexto.SaveChanges();
            contexto.Dispose();
        }

        public override List<Infractor> All()
        {
            ContextoInfraccion contexto = new ContextoInfraccion();
            List<TblInfractor> listaBD = new List<TblInfractor>();

            listaBD = contexto.TblInfractor.OrderBy(A => A.nombres).ToList();

            //El repositorio de infractor crea el objeto Licencia mediante un método privado
            foreach (var item in listaBD)
            {
                Infractor obj = new Infractor(new InfractorId(item.id), item.numIdentificacion, item.nombres, item.apellidos, item.tipoIdentificacion,
                    this.LicenciaConduccionFromPK((int)item.pk_licenciaconduccion),
                    new Direccion(item.domicilio, item.municipio, item.localidad, item.codigoPostal)
                    );

                lista.Add(obj);
            }


            contexto.Dispose();
            return lista;
        }

        public override int Count()
        {
            return All().Count;
        }
        
        #endregion

        #region Métodos Nuevos
        public override InfractorId FromIdentificacion(string numIdentificacion)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();

            TblInfractor obj = contexto.TblInfractor.Where(I => I.numIdentificacion == numIdentificacion).FirstOrDefault();            
            contexto.Dispose();

            return new InfractorId(obj.id);
        }
        #endregion


        #region Métodos de Base de Datos
        private LicenciaConduccion LicenciaConduccionFromPK(int pkLicConduccion)
        {
            ContextoInfraccion contexto = new ContextoInfraccion();

            TblLicenciaConduccion licConduccionBD = contexto.TblLicenciaConduccion.Where(L => L.pk_licenciaconduccion == pkLicConduccion).FirstOrDefault();
            TblSecretariaDeTransito secTransitoBD = contexto.TblSecretariaDeTransito.Where(S => S.pk_secretaria == licConduccionBD.pk_secretaria).FirstOrDefault();
            contexto.Dispose();

            LicenciaConduccion oLicencia = new LicenciaConduccion(licConduccionBD.numero, (DateTime)licConduccionBD.fechaExpedicion, (DateTime)licConduccionBD.fechaVencimiento, licConduccionBD.categoria, new SecretariaDeTransitoId(secTransitoBD.id));

            //Asignar la llave primaria de la BD
            oLicencia.PK = licConduccionBD.pk_licenciaconduccion;
            
            return oLicencia;
        }
        
        #endregion
    }
}
